/*
 * @Author: Troubadour 2276791354@qq.com
 * @Date: 2024-03-30 16:30:43
 * @LastEditors: Troubadour 2276791354@qq.com
 * @LastEditTime: 2024-04-12 22:23:50
 * @Version:
 * @Description:
 */

#include "esp_01.h"
#include "usart.h"
#include <string.h>
#include "cmsis_os.h"
#include "FreeRTOS.h"
#include "cJSON.h"
#include <stdlib.h>


#define WIFI_UART_HANDLE (huart3)
#define WIFI_Delay_Ms(ms) osDelay(ms)

#define WIFI_SSID "Troubadour-5G-Phone"
#define WIFI_PWD "QQQ666666"
#define WIFI_CNT_CMD "AT+CWJAP=\"" WIFI_SSID "\",\"" WIFI_PWD "\"\r\n"

#define NET_GETTIME_REQ "GET /rest/api3.do?api=mtop.common.getTimestamp HTTP/1.1\r\n"\
                        "Content-Type: application/json;charset=utf-8\r\n"\
                        "Host: api.m.taobao.com\r\n"\
                        "Connection: Keep Alive\r\n"

/* MQTT配置。ID中逗号需要加反斜杠 */
#define MQTT_CLENT_ID "a1HZwVN3HUJ.D001|securemode=2\\,signmethod=hmacsha256\\,timestamp=1711974838578|"
#define MQTT_CLENT_USER "D001&a1HZwVN3HUJ"
#define MQTT_CLENT_PWD "ea39df06d70d99472d27185f93c1482d3174fea4955ee7bedaa8caf5113975d3"
#define MQTT_CFG_CMD "AT+MQTTUSERCFG=0,1,\"" MQTT_CLENT_ID "\",\"" MQTT_CLENT_USER "\",\"" MQTT_CLENT_PWD "\",0,0,\"\"\r\n"

// #define MQTT_HOST "iot-06z00ehmf4au728.mqtt.iothub.aliyuncs.com"
#define MQTT_HOST "a1HZwVN3HUJ.iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define MQTT_CNT_CMD "AT+MQTTCONN=0,\"" MQTT_HOST "\",1883,0\r\n"

// #define MQTT_PUB_TOPIC "/ib8ajH3wGfU/ESP_01S/user/cmd"
#define MQTT_PUB_TOPIC "/sys/a1HZwVN3HUJ/D001/thing/event/property/post"

static uint8_t WiFi_SendBuff[300] = {0}, WiFi_TempBuff[300] = {0},  WiFi_RecvBuff[256] = {0};
ESP_Buf_TyP WiFiBufDataQueue[WIFI_BUFFER_NUM] = {0};

ESP_01_TyP esp_module = {
    .state = WIFI_RST,
};
/* Test data. */
uint8_t PublishPoly[] = "Testdata.";

MQTTData mqtt_message;
WIFI_ENUM reState;
static uint8_t ErrorCnt = 0, BusyCnt = 0;

#define Message_ID  "1711973102724"




/* 设备上传数据 */
DeviceReport deviceUpReport = {
    .mode = MODE_AUTO,
    .Color = COLOR_WHITE
};

void packJsonUpdata(uint8_t *packBuff)
{
    uint8_t DeviceTimer[3] = {12, 13, 14};

    /* 数据太长不能超过128字节，会出错。所以用AT+MQTTPUBRAW */
    sprintf((char *)packBuff, "{"
    "\"id\":%s,"
    "\"params\":{"
        "\"powerstate\":%d,"
        "\"DeviceTimer\":[%d,%d,%d],"
        "\"mode\":%d,"
        "\"brightness\":%d,"
        "\"Ultra\":%.2f,"
        "\"Color\":%d,"
        "\"ManSensor\":%d,"
        "\"SRuntime\":%d,"
        "\"LED_State\":%d"
    "},"
    "\"version\":\"1.0\","
    "\"method\":\"thing.event.property.post\"}",
    Message_ID,
    deviceUpReport.powerstate,
    DeviceTimer[0], DeviceTimer[1], DeviceTimer[2],
    deviceUpReport.mode,
    deviceUpReport.brightness,
    deviceUpReport.Ultra,
    deviceUpReport.Color,
    deviceUpReport.ManSensor,
    deviceUpReport.SRuntime,
    deviceUpReport.LED_State);
}

HAL_StatusTypeDef parseMQTTData(const char *input, MQTTData *data)
{
    char *str_topic = (char *)data->topic,
        *str_payload = (char *)data->payload;
    int client_Id = 0, payloadlen = 0;

    uint8_t result = sscanf(input, "+MQTTSUBRECV:%d,\"%128[^\"]\",%d,%256[^*]", &client_Id, str_topic, &payloadlen, str_payload);

    if (result == 4)
    {
        // 解析成功
        data->client_Id = client_Id;
        data->payloadlen = payloadlen;
        return HAL_OK;
    }
    else
    {
        // 解析失败
        return HAL_ERROR;
    }
}

void Esp_01_RecvHandle(uint8_t *recvBuf, uint16_t len)
{
    static uint32_t LastTimer = 0;
    static uint16_t DataCnt = 0;
    uint8_t CleanFlag = 1;

    if ((HAL_GetTick() - LastTimer) > 5)
    {
        DataCnt = 0;
        memset(WiFi_RecvBuff, 0, sizeof(WiFi_RecvBuff));
    }

    if (sizeof(WiFi_RecvBuff) > (DataCnt + len))
    {
        memcpy(WiFi_RecvBuff + DataCnt, recvBuf, len);
        DataCnt += len;
    }
    else
    {
        memset(WiFi_RecvBuff, 0, sizeof(WiFi_RecvBuff));
        memcpy(WiFi_RecvBuff, recvBuf, len);;
        DataCnt = len;
    }

    if ((esp_module.state == WIFI_CNT) && (strstr((const char *)WiFi_RecvBuff, "+CIPSNTPTIME:") != NULL))
    {
        uint8_t num = 0;
        /* +CIPSNTPTIME:Thu Jan  1 08:00:13 1970 */
        num = sscanf((const char *)WiFi_RecvBuff, "+CIPSNTPTIME:%*s %*s %d %d:%d:%d %d",
            &deviceUpReport.time_d, &deviceUpReport.time_h, &deviceUpReport.time_m, &deviceUpReport.time_s, &deviceUpReport.time_y);
        if (deviceUpReport.time_y >= 2024)
        {
            if (deviceUpReport.time_s++ >= 59)
            {
                deviceUpReport.time_s = 0;
                if (deviceUpReport.time_m++ >= 59)
                {
                    deviceUpReport.time_m = 0;
                    if (deviceUpReport.time_h++ >= 23)
                    {
                        deviceUpReport.time_h = 0;
                    }
                }
            }

            printf("parse timer. Q: %d \r\n", num);
            printf("parse timer. Data: %s \r\n", WiFi_RecvBuff);
            printf("Time D: %d \r\n", deviceUpReport.time_d);
            printf("Time Y: %d \r\n", deviceUpReport.time_y);
            printf("Time H: %d \r\n", deviceUpReport.time_h);
            printf("Time M: %d \r\n", deviceUpReport.time_m);
            printf("Time S: %d \r\n", deviceUpReport.time_s);
        }
    }

    if (strstr((const char *)WiFi_RecvBuff, "busy p") != NULL)
    {
        // printf("busy p................. \r\n");
        if (BusyCnt++ == 10)
        {
            BusyCnt = 0;
            if (esp_module.state != WIFI_BUSY)
            {
                reState = esp_module.state;
            }
            esp_module.state = WIFI_BUSY;
        }
    }
    else if (esp_module.waitData == 1)
    {
        if (strstr((const char *)WiFi_RecvBuff, (const char *)esp_module.response) != NULL)
        {
            esp_module.waitData = 0;
        }
    }
    else if (strstr((const char *)WiFi_RecvBuff, "WIFI DISCONNECT") != NULL)
    {
        esp_module.state = WIFI_INIT;
    }
    else if (strstr((const char *)WiFi_RecvBuff, "WIFI CONNECTED") != NULL)
    {
        esp_module.state = WIFI_CNT;
    }
    else if (esp_module.state == WIFI_MQTT_WORK)
    {
        if (strstr((const char *)WiFi_RecvBuff, "+MQTTSUBRECV") != NULL)
        {
            if (parseMQTTData((const char *)WiFi_RecvBuff, &mqtt_message) == HAL_OK)
            {
                /* code */
                // printf("Client id: %d \r\n", mqtt_message.client_Id);
                // printf("Topic: %s \r\n", mqtt_message.topic);
                // printf("payload len: %d \r\n", mqtt_message.payloadlen);
                // printf("payload: %s \r\n", mqtt_message.payload);
            }
        }
    }
    else
    {
        CleanFlag = 0;
    }

    if (strstr((const char *)WiFi_RecvBuff, "ERROR") != NULL)
    {
        if (ErrorCnt++ >= 30)
        {
            printf("\r\n \r\n ************************** Check ERROR. ******************** \r\n \r\n");
            ErrorCnt = 0;
            esp_module.state = WIFI_RST;
        }
    }
    else
    {
        (ErrorCnt == 0) ? (ErrorCnt) : (ErrorCnt--);
    }


    if (CleanFlag)
    {
        memset(WiFi_RecvBuff, 0, DataCnt);
        DataCnt = 0;
    }
}


static HAL_StatusTypeDef Esp_01_SendCmd(const uint8_t *cmd, uint8_t *response, uint32_t timerout)
{
    uint32_t LastTime = HAL_GetTick();

    esp_module.waitData = 1;
    esp_module.response = response;

    HAL_UART_Transmit(&WIFI_UART_HANDLE, cmd, strlen((const char *)cmd), timerout);

    while (((HAL_GetTick() - LastTime) < timerout) && (esp_module.waitData == 1))
    {
        osDelay(5);
    }

    esp_module.waitData = 0;
    return ((HAL_GetTick() - LastTime < timerout)) ? (HAL_OK) : (HAL_ERROR);
}

void Esp_01_Task(void)
{
    switch (esp_module.state)
    {
    case WIFI_RST:
        osDelay(3000);
        if (Esp_01_SendCmd("AT+RST\r\n", "OK",1000) == HAL_OK)
        {
            esp_module.state = WIFI_INIT;
        }
        osDelay(3000);

    case WIFI_INIT:
        printf("WIFI_INIT \r\n");
        if (Esp_01_SendCmd("AT\r\n", "OK", 1000) == HAL_OK)
        {
            WIFI_Delay_Ms(1000);
            if (Esp_01_SendCmd("AT+CWMODE=1\r\n", "OK",1000) == HAL_OK)
            {
                WIFI_Delay_Ms(1000);
                if (Esp_01_SendCmd(WIFI_CNT_CMD, "WIFI CONNECTED",10000) == HAL_OK)
                {
                    esp_module.state = WIFI_CNT;
                }
            }
        }
        WIFI_Delay_Ms(1000);
        break;

    case WIFI_CNT:
        printf("WIFI_CNT \r\n");
        if (Esp_01_SendCmd("AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n", "OK", 1000) == HAL_OK)
        {
            WIFI_Delay_Ms(1000);
            if (Esp_01_SendCmd("AT+CIPSNTPTIME?\r\n", "OK", 1000) == HAL_OK)
            {
                WIFI_Delay_Ms(100);
                if (deviceUpReport.time_y > 2000)
                {
                    if (Esp_01_SendCmd(MQTT_CFG_CMD, "OK", 1000) == HAL_OK)
                    {
                        WIFI_Delay_Ms(100);
                        if (Esp_01_SendCmd(MQTT_CNT_CMD, "OK", 1000) == HAL_OK)
                        {
                            esp_module.state = WIFI_MQTT_SUB;
                        }
                    }
                }
            }
        }
        WIFI_Delay_Ms(2000);
        break;

    case WIFI_MQTT_SUB:
        printf("WIFI_MQTT_SUB \r\n");
        if (Esp_01_SendCmd("AT+MQTTSUB=0,\"/sys/a1HZwVN3HUJ/D001/thing/service/property/set\",0\r\n", "OK", 1000) == HAL_OK)
        {
            esp_module.state = WIFI_MQTT_WORK;
        }
        WIFI_Delay_Ms(2000);
        break;

    case WIFI_MQTT_WORK:
        memset(WiFi_SendBuff, 0, sizeof(WiFi_SendBuff));
        memset(WiFi_TempBuff, 0, sizeof(WiFi_TempBuff));
        packJsonUpdata(WiFi_TempBuff);
        sprintf((char *)WiFi_SendBuff, "AT+MQTTPUBRAW=0,\"%s\",%d,0,0\r\n", MQTT_PUB_TOPIC, strlen((const char *)WiFi_TempBuff));
        if (Esp_01_SendCmd((const uint8_t *)WiFi_SendBuff, ">", 1000) == HAL_OK)
        {
            if (Esp_01_SendCmd((const uint8_t *)WiFi_TempBuff, "OK", 1000) == HAL_OK)
            {
                printf("Timer updata successful. \r\n");
            }
            else
            {
                printf("Timer 2 updata error. \r\n");
                WIFI_Delay_Ms(5000);
            }
        }
        else
        {
            printf("Timer updata error. \r\n");
            WIFI_Delay_Ms(5000);
        }

        WIFI_Delay_Ms(500);
        break;

    case WIFI_BUSY:
        printf("WIFI_BUSY \r\n");
        WIFI_Delay_Ms(3000);
        if (Esp_01_SendCmd("AT\r\n", "OK", 3000) == HAL_OK)
        {
            if (Esp_01_SendCmd("AT\r\n", "OK", 3000) == HAL_OK)
            {
                esp_module.state = reState;
            }
        }
        WIFI_Delay_Ms(3000);
        break;

    default:
        break;
    }
}


